<template>
	<view class="">
		<!-- #ifdef H5 -->
		<view class="jushi-watermark">
			<canvas :canvas-id="item.canvasId" :style="{width:item.canvasWidth,height:item.canvasHeight}"
				v-for="(item,index) in canvasSize"></canvas>
		</view>
		<!-- #endif -->
		<!-- #ifdef MP-WEIXIN -->
		<view class="content">
			<!-- 获取有水印的图片过程 必须使canvas显示 获取完成后再隐藏掉canvas 配合canvas样式定位 使其错位 -->
			<!-- canvas的隐藏 在小程序中 使用 v-if或display：none 都不生效   使用hidden属性 true隐藏 false显示 -->
			<canvas :style="{width:canvasWidth,height:canvasHeight}" canvas-id="jushiCanvas" :hidden="flagC"></canvas>
		</view>
		<!-- #endif -->
	</view>
</template>

<script>
	export default {
		name: 'jushi-watermark',
		props: {
			fontColor: { //水印文字颜色
				type: String,
				default: '#000000'
			}
		},
		data() {
			return {
				canvasSize: [],
				flagC: false,
				canvasWidth: '',
				canvasHeight: ''
			}
		},
		methods: {
			/**
			 * 添加水印函数，通过实例调用该函数
			 * @param {Object} options 
			 * 			{filePath:'图片地址', texts:['水印1', '水印2']}
			 */
			addWaterMark(options) {
				// #ifdef H5
				this.addWaterMarkH5(options)
				// #endif
				// #ifdef MP-WEIXIN
				this.addWaterMarkWX(options)
				// #endif
			},
			addWaterMarkH5(options) { //h5添加水印
				this.canvasSize = []
				uni.getImageInfo({
					src: options.filePath,
					success: (image) => {
						this.canvasSize.push({
							canvasWidth: `${image.width}px`,
							canvasHeight: `${image.height}px`,
							canvasId: `jushi${image.width}`
						})
						var texts = (options.texts || []).reverse()
						this.drawImage(options.filePath, texts)
					},
					fail(e) {
						console.log(JSON.stringify(e))
					}
				})
			},
			drawImage(filePath, texts) { //绘制单个图片 H5使用
				uni.showLoading({
					title: '图片处理中···'
				});
				const ctx = uni.createCanvasContext(this.canvasSize[0].canvasId, this)
				uni.getImageInfo({
					src: filePath,
					success: (image) => {
						//先画目标图片
						ctx.drawImage(filePath, 0, 0)
						let fontSize = Math.floor(image.width / 25)
						//设置字体大小、样式
						ctx.setFontSize(fontSize)
						ctx.setFillStyle(this.fontColor)
						// 设置阴影
						ctx.shadowColor = this.fontColor
						ctx.shadowOffsetX = 0
						ctx.shadowOffsetY = 0
						let max = (image.width-fontSize)/fontSize //图片上一行能显示的最大字数
						let marks = []
						texts.forEach((mark,index)=>{
							//测量出最长文字的宽
							// console.log('文字宽：'+ctx.measureText(mark).width)
							if(mark.length<=max){
								marks.push({
									mark:mark,//水印文字
									start:fontSize/2 //第一个字的起点位置
								})
							}else{
								marks.push({
									mark:mark.substring(max),
									start:fontSize/2+fontSize*3 //第一个字的起点位置，+fontSize*3是因为此水印为当前mark的换行，因此缩进3字符
								})
								marks.push({
									mark:mark.substring(0,max),
									start:fontSize/2 //第一个字的起点位置
								})
							}
						})
						//绘制水印文字
						marks.forEach((mark, index) => {
							ctx.fillText(mark.mark, mark.start, this.getHeightOffset(
								image.height, index, fontSize))
						});
						ctx.draw(false, (() => {
							setTimeout(() => {
								uni.canvasToTempFilePath({
									canvasId: this.canvasSize[0].canvasId,
									fileType: 'jpg',
									quality: 1,
									success: (res) => {
										this.$emit('callback', res
											.tempFilePath)
									},
									fail: (err) => {
										console.log(err)
									},
									complete: () => {
										uni.hideLoading()
									}
								}, this)
							}, 300)
						}))
					},
					fail: (e) => {
						uni.hideLoading()
					}
				})
			},
			addWaterMarkWX(options) {// 微信小程序添加水印
				uni.showLoading({
					title: '图片加载中...',
					mask: true
				})
				this.flagC = false
				let fillTexts = options.texts.reverse()
				let filePath = options.filePath
				uni.getImageInfo({
					// 注意此时的地址是正常的图片地址 以下是给图片添加水印返回新的url地址
					src: filePath,
					success: res => {
						this.canvasWidth = `${res.width}px`
						this.canvasHeight = `${res.height}px`
						// 在自定义组件内 需要传递第二参数 this canvas才生效
						var ctx = uni.createCanvasContext('jushiCanvas', this)
						ctx.clearRect(0, 0, res.width, res.height)
						ctx.beginPath()
						// 第一个参数是图片 第二、三是图片在画布位置 第四、五是将图片绘制成多大宽高（不写四五就是原图宽高）
						ctx.drawImage(filePath, 0, 0)

						// 为图片添加水印
						// ctx.translate(res.width / 2, res.height / 2)
						// ctx.rotate(45 * Math.PI / 180)
						let fontSize = Math.floor(res.width / 25)
						ctx.setFontSize(fontSize)
						ctx.setFillStyle(this.fontColor)
						ctx.shadowColor = this.fontColor
						ctx.shadowOffsetX = 0
						ctx.shadowOffsetY = 0
						let max = (res.width-fontSize)/fontSize //图片上一行能显示的最大字数
						let marks = []
						fillTexts.forEach((mark,index)=>{
							//测量出最长文字的宽
							// console.log('文字宽：'+ctx.measureText(mark).width)
							if(mark.length<=max){
								marks.push({
									mark:mark,//水印文字
									start:fontSize/2 //第一个字的起点位置
								})
							}else{
								marks.push({
									mark:mark.substring(max),
									start:fontSize/2+fontSize*3 //第一个字的起点位置，+fontSize*3是因为此水印为当前mark的换行，因此缩进3字符
								})
								marks.push({
									mark:mark.substring(0,max),
									start:fontSize/2 //第一个字的起点位置
								})
							}
						})
						//绘制水印文字
						marks.forEach((mark, index) => {
							ctx.fillText(mark.mark, mark.start, this.getHeightOffset(
								res.height, index, fontSize))
						});
						// console.log('width = '+res.width+'   height = '+res.height)
						// 开始绘制添加水印的图片并显示在页面中
						ctx.draw(false, () => {
							setTimeout(() => {
								uni.canvasToTempFilePath({
									canvasId: "jushiCanvas",
									fileType: 'jpg',
									// quality:'0.5',
									success: res => {
										// 注意此时的地址是加了水印的图片地址（直接url输入浏览器也可以查看包含水印）
										this.flagC = true
										this.$emit('callback', res
											.tempFilePath)
									},
									fail(e) {
										console.log(JSON.stringify(e))
									},
									complete() {
										uni.hideLoading()
									}
								}, this)
								// 在自定义组件内 需要传递第二参数 this canvas才生效
							}, 500)
						});
					},
					fail(e) {
						console.log(JSON.stringify(e))
						uni.hideLoading()
					}
				})
			},
			getHeightOffset(height, index, fontSize) {
				return index == 0 ? (height - fontSize) : (height - (index * fontSize) - fontSize)-(index*(fontSize/3))
			}
		}
	}
</script>

<style>
	.content {
		position: fixed;
	}

	canvas {
		border: solid 1px gray;
		position: absolute;
		left: 5000rpx;
		width: 0;
		height: 0;
		overflow: hidden;
	}

	.jushi-watermark {
		position: fixed;
	}
</style>